/*
 * Copyright (c) 2016. 恒昌互联网运营中心.
 */
package com.credithc.eagleeye.agent.strategy;
import com.credithc.eagleeye.agent.IEagleEyeAgent;
import com.credithc.eagleeye.agent.bean.EagleEyeAgentConfig;
import com.credithc.eagleeye.agent.util.HostUtil;
import com.credithc.eagleeye.thread.ThreadFactoryImpl;
import com.credithc.eagleeye.vo.RpcTraceInfoVo;
import org.apache.commons.lang3.StringUtils;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
 * 描 述: <br/>
 * 作 者: zhangjin<br/>
 * 创 建：2016年09月30日<br/>
 * 版 本：v1.0.0<br>
 * <p/>
 * 历 史: (版本) 作者 时间 注释 <br/>
 */
public abstract class AbsEagleEyeAgent implements IEagleEyeAgent {
    private static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2;
    /**
     * 最大本地保留数据条数，防止应用内存溢出，假设每条占用1KB，最大会占用1GB内存
     */
    private static final int MAX_QUEUE_SIZE = 10240;
    /**
     * 发送鹰眼数据线程池，如果队列满了，则放弃旧的数据
     */
    private static final ExecutorService threadPool = new ThreadPoolExecutor(
            CORE_POOL_SIZE,
            CORE_POOL_SIZE,
            60*1000, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(MAX_QUEUE_SIZE),
            new ThreadFactoryImpl("send2EagleEyeAgent_"),
            new ThreadPoolExecutor.DiscardOldestPolicy());
    /**
     * 发送鹰眼数据的实现方法
     *
     * @param rpcTraceInfoVo
     */
    protected abstract boolean doSend2EagleEye(final RpcTraceInfoVo rpcTraceInfoVo);
    /**
     * 最大重试次数
     */
    private static final int MAX_RETRY_TIMES = 2;
    /**
     * 鹰眼agent传输方式配置
     */
    EagleEyeAgentConfig eagleEyeAgentConfig;
    protected AbsEagleEyeAgent(EagleEyeAgentConfig eagleEyeAgentConfig) {
        this.eagleEyeAgentConfig = eagleEyeAgentConfig;
    }
    @Override
    public EagleEyeAgentConfig getEagleEyeAgentConfig() {
        return eagleEyeAgentConfig;
    }
    @Override
    public void send2EagleEye(final RpcTraceInfoVo rpcTraceInfoVo) {
        rpcTraceInfoVo.setPlatformName(eagleEyeAgentConfig.getAgentPlatform());
        rpcTraceInfoVo.setEnv(eagleEyeAgentConfig.getAgentEnv());
        if (StringUtils.isBlank(rpcTraceInfoVo.getClientName())) {
            rpcTraceInfoVo.setClientName(eagleEyeAgentConfig.getAgentClientName());
        }
        if (StringUtils.isBlank(rpcTraceInfoVo.getClientHost())) {
            rpcTraceInfoVo.setClientHost(HostUtil.getIp());
        }
        threadPool.execute(new Runnable() {
            @Override
            public void run() {
                for(int i = 0; i < MAX_RETRY_TIMES; i++) {
                    boolean success = doSend2EagleEye(rpcTraceInfoVo);
                    if (success) {
                        break;
                    }
                }
            }
        });
    }

}
